#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include<netinet/in.h>
#include <arpa/inet.h>
#include<cstring>
#include "Log.hpp"
#include"InetAddr.hpp"
const int gsocketfd = -1;
const uint16_t glocalport = 8888;

enum{
    SOCKET_ERROR=1,
    BIND_ERROR
};

class UDPServer
{
public:
    UDPServer(uint16_t localport = glocalport)
        : _localport(localport),
          _isrunning(false),
          _socketfd(gsocketfd)
    {
    }
    ~UDPServer()
    {
        if(_socketfd>gsocketfd)
        {
            close(_socketfd);
           // _isrunning=false;
        }
    }
    void Init()
    {
        //创建UDP文件
        _socketfd = socket(AF_INET,SOCK_DGRAM,0);
        if(_socketfd<0)
        {
            LOG(FATAL,"create socket error\n");
            exit(SOCKET_ERROR);
        }
        LOG(DEBUG,"create socket success,socketfd:%d\n",_socketfd);

        //bind
        struct sockaddr_in local;
        memset(&local,0,sizeof(local));
        local.sin_family=AF_INET;
        local.sin_port=htons(_localport);
        local.sin_addr.s_addr=INADDR_ANY;
        int n=bind(_socketfd,(struct sockaddr*)&local,sizeof(local));
        if(n<0)
        {
             LOG(FATAL,"bind error\n");
            exit(BIND_ERROR);
        }
        LOG(DEBUG,"bind success!\n");
    }
    void Start()
    {
        _isrunning=true;
        char buffer[1024];
        while(_isrunning)
        {
            struct sockaddr_in peer;
            socklen_t len=sizeof(peer);
            int n=recvfrom(_socketfd,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&peer,&len);
            if(n>0)
            {
                InetAddr addr(peer);
                buffer[n]='\0';
                std::cout<<"["<<addr.IP()<<":"<<addr.Port()<<"]#"<<buffer<<std::endl;

                std::string echo="[udp_server echo]:";
                echo+=buffer;
                sendto(_socketfd,echo.c_str(),echo.size(),0,(struct sockaddr*)&peer,len);
            }
            else
            {
                std::cout << "recvfrom ,  error"  << std::endl; 
            }
        }
    }

private:
    int _socketfd;
    uint16_t _localport;
    bool _isrunning;
};